package com.lanxiao.cloud.modules.oauth.application;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.lanxiao.cloud.common.core.dto.PageQuery;
import com.lanxiao.cloud.common.core.dto.ResultModel;
import com.lanxiao.cloud.common.core.enums.DelFlagEnum;
import com.lanxiao.cloud.common.core.enums.StateEnum;
import com.lanxiao.cloud.common.core.utils.StringUtils;
import com.lanxiao.cloud.common.web.service.ILog;
import com.lanxiao.cloud.modules.oauth.application.assembler.RoleAssembler;
import com.lanxiao.cloud.modules.oauth.application.dto.BasicsRoleDto;
import com.lanxiao.cloud.modules.oauth.application.dto.RolePageDto;
import com.lanxiao.cloud.modules.oauth.application.dto.RoleQuery;
import com.lanxiao.cloud.modules.oauth.application.dto.UserRoleDto;
import com.lanxiao.cloud.modules.oauth.domain.model.Role;
import com.lanxiao.cloud.modules.oauth.domain.model.UserRole;
import com.lanxiao.cloud.modules.oauth.infrastructure.repository.RoleMapper;
import com.lanxiao.cloud.modules.oauth.infrastructure.repository.UserRoleMapper;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;

/**
 * @author ：qiaoliang
 * @date ：2021-09-16
 */
@Component
public class RoleQueryManager implements ILog<Role, Long> {

  private final RoleMapper roleMapper;
  private final UserRoleMapper userRoleMapper;
  private final RoleAssembler roleAssembler;

  public RoleQueryManager(
      RoleMapper roleMapper,
      UserRoleMapper userRoleMapper,
      RoleAssembler roleAssembler) {
    this.roleMapper = roleMapper;
    this.userRoleMapper = userRoleMapper;
    this.roleAssembler = roleAssembler;
  }

  /**
   *  分页查询角色列表
   *
   * @author ：qiaoliang
   * @param query : 查询条件
   * @param page : 分页条件
   * @return com.lanxiao.cloud.common.core.dto.ResultModel<com.lanxiao.cloud.modules.oauth.application.dto.RolePageDto>
   * @date 2021-09-16 11:39
   */
  public ResultModel<RolePageDto> page(RoleQuery query, PageQuery page) {
    LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper
        .eq(Objects.nonNull(query.getState()), Role::getState, query.getState())
        .eq(StringUtils.isNotBlank(query.getMark()), Role::getMark, query.getMark())
        .eq(StringUtils.isNotBlank(query.getName()), Role::getName, query.getName() + "%")
        .eq(Role::getDelFlag, DelFlagEnum.NOT_DELETE);
    return roleAssembler.toRolePageDto(
        roleMapper.selectPage(new Page<>(page.getPage(), page.getSize()), queryWrapper));
  }

  /**
   *  查询可分配角色集合
   *
   * @author ：qiaoliang

   * @return java.util.List<com.lanxiao.cloud.modules.oauth.application.dto.BasicsRoleDto>
   * @date 2021-11-01 10:36
   */
  public List<BasicsRoleDto> query() {
    LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper
        .eq(Role::getDelFlag, DelFlagEnum.NOT_DELETE)
        .eq(Role::getState, StateEnum.NORMAL);
    return roleAssembler.toBasicsRoleDto(roleMapper.selectList(queryWrapper));
  }

  /**
   * 通过用户ID获取角色列表
   *
   * @author ：qiaoliang
   * @param userId : 用户ID
   * @return java.util.List<com.lanxiao.cloud.modules.oauth.application.dto.UserRoleDto>
   * @date 2021-09-16 13:47
   */
  public List<UserRoleDto> userRoleQuery(Long userId) {
    return roleAssembler.toUserRoleDto(roleMapper.findByUserRole(userId));
  }


  /**
   *  回填用户角色
   *
   * @author ：qiaoliang
   * @param userIds : 用户ID
   * @return java.util.Map<java.lang.Long, java.lang.String>
   * @date 2021-10-26 14:14
   */
  public Map<Long, String> findByUserIds(List<Long> userIds) {

    final List<UserRole> userRoles = userRoleMapper.selectList(
        new LambdaQueryWrapper<UserRole>().in(UserRole::getUserId, userIds)
    );
    if (CollUtil.isEmpty(userRoles)) {
      return Maps.newHashMap();
    }
    final Map<Long, List<Long>> userRoleMap = userRoles.stream()
        .collect(Collectors.groupingBy(UserRole::getUserId,
            Collectors.mapping(UserRole::getRoleId, Collectors.toList())));

    final List<Role> roles = roleMapper.selectList(new LambdaQueryWrapper<Role>().in(Role::getId,
            userRoleMap.values().stream().flatMap(Collection::parallelStream).distinct().collect(Collectors.toList()))
        .eq(Role::getState, StateEnum.NORMAL)
        .eq(Role::getDelFlag, DelFlagEnum.NOT_DELETE));

    Map<Long, String> map = new HashMap<>(userIds.size());
    userIds.forEach(userId-> {
      final List<Long> roleIds = userRoleMap.get(userId);
      map.put(userId, roles.stream().filter(role -> roleIds.contains(role.getId()))
          .map(Role::getName)
          .reduce((v,i)->v+","+i).orElse(""));
    });
    return map;
  }

  @Override
  public Role selectById(Long id) {
    return roleMapper.selectById(id);
  }

}
